package com.domainchen.miniMongodb.core;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.XMLOutputter;

import com.google.gson.Gson;

/**
 * @author domainchen E-mail:cytxiamen@163.com
 * @version 创建时间：2016年8月26日 上午11:46:01
 * @类说明
 */

public class MiniMongodb {

	private final static String _UUID = "_uuid";

	/**
	 * 启动数据库
	 * 
	 * @param databasePath
	 */
	public void startUpDatabase() throws Exception {
		FileOutputStream fileos = new FileOutputStream(Appconst.DATABASE_NAME);
		Document doc = new Document();
		Element rootElement = new Element("database");

		Element testTable = new Element("table");
		testTable.setAttribute("name", "test");

		Element indexTable = new Element("table");
		indexTable.setAttribute("name", "system.indexs");

		Element userTable = new Element("table");
		userTable.setAttribute("name", "system.users");

		rootElement.addContent(testTable);
		rootElement.addContent(indexTable);
		rootElement.addContent(userTable);

		doc.setRootElement(rootElement);

		XMLOutputter output = new XMLOutputter();
		output.output(doc, fileos);
		System.out.println("数据库miniMongodb 初始化/启动成功啦..................................");

	}

	
	
	/**
	 * 保存数据
	 * 
	 * @param tableName
	 * @param po
	 * @return
	 * @throws Exception
	 */
	public boolean save(String tableName, Object po) throws Exception {
		boolean isSave = false;
		FileInputStream fileIs = new FileInputStream(Appconst.DATABASE_NAME);
		SAXBuilder sAXBuilder = new SAXBuilder();
		Document doc = sAXBuilder.build(fileIs);
		Element rootElement = doc.getRootElement();
		Gson gson = new Gson();
		boolean flag = false;
		for (Element element : rootElement.getChildren()) {
			if (tableName.equals(element.getAttributeValue("name"))) {
				Map base = new HashMap();
				base.put(_UUID, UUID.randomUUID().toString());

				Element dataElement = new Element("data");
				String data = gson.toJson(po);

				Map map = gson.fromJson(data, Map.class);
				base.putAll(map);
				dataElement.addContent(gson.toJson(base));
				element.addContent(dataElement);
				flag = true;
			}
		}

		if (!flag) {
			// 不存在新建表
			System.out.println("不存在表,新建表");
			Element newTable = new Element("table");
			newTable.setAttribute("name", tableName);

			Map base = new HashMap();
			base.put(_UUID, UUID.randomUUID().toString());

			Element dataElement = new Element("data");
			String data = gson.toJson(po);

			Map map = gson.fromJson(data, Map.class);
			base.putAll(map);
			dataElement.addContent(gson.toJson(base));
			newTable.addContent(dataElement);

			rootElement.addContent(newTable);
		}

		XMLOutputter output = new XMLOutputter();
		output.output(doc, new FileOutputStream(Appconst.DATABASE_NAME));

		System.out.println("添加数据成功啦...................................");

		isSave = true;
		return isSave;
	}

	/**
	 * 修改数据
	 * 
	 * @param tableName
	 * @param po
	 * @throws Exception
	 */
	public boolean update(String tableName, Object po) throws Exception {
		boolean isUpdate = false;
		FileInputStream fileIs = new FileInputStream(Appconst.DATABASE_NAME);
		SAXBuilder sAXBuilder = new SAXBuilder();
		Document doc = sAXBuilder.build(fileIs);
		Element rootElement = doc.getRootElement();
		Gson gson = new Gson();
		boolean flag = false;
		for (Element element : rootElement.getChildren()) {
			if (tableName.equals(element.getAttributeValue("name"))) {
				flag = true;
				List<Element> subElementList = element.getChildren();
				for (Element dataElement : subElementList) {
					Map dataMap = gson.fromJson(dataElement.getText(), Map.class);
					Map newmp = gson.fromJson(gson.toJson(po), Map.class);
					if (dataMap.get(_UUID).equals(newmp.get(_UUID))) {
						dataMap.putAll(newmp);

						Element newDataElement = new Element("data");
						newDataElement.setText(gson.toJson(dataMap));

						element.removeContent(dataElement);
						element.addContent(newDataElement);

						break;
					}
				}

			}
		}

		if (!flag) {
			throw new Exception("table '" + tableName + "' is not exits");
		}
		XMLOutputter output = new XMLOutputter();
		output.output(doc, new FileOutputStream(Appconst.DATABASE_NAME));

		System.out.println("修改数据成功啦...................................");

		isUpdate = true;
		return isUpdate;
	}

	/**
	 * 删除数据
	 * 
	 * @param tableName
	 * @param po
	 * @return
	 * @throws Exception
	 */
	public boolean delete(String tableName, Object po) throws Exception {
		boolean isDel = false;
		FileInputStream fileIs = new FileInputStream(Appconst.DATABASE_NAME);
		SAXBuilder sAXBuilder = new SAXBuilder();
		Document doc = sAXBuilder.build(fileIs);
		Element rootElement = doc.getRootElement();
		Gson gson = new Gson();
		boolean flag = false;
		for (Element element : rootElement.getChildren()) {
			if (tableName.equals(element.getAttributeValue("name"))) {
				flag = true;
				List<Element> subElementList = element.getChildren();
				for (Element dataElement : subElementList) {
					Map dataMap = gson.fromJson(dataElement.getText(), Map.class);
					Map newmp = gson.fromJson(gson.toJson(po), Map.class);
					if (dataMap.get(_UUID).equals(newmp.get(_UUID))) {
						isDel = true;
						element.removeContent(dataElement);
						break;
					}
				}
			}

		}
		if (!flag) {
			throw new Exception("table '" + tableName + "' is not exits");
		}
		if (!isDel) {
			throw new Exception("the record is not exits");
		}
		XMLOutputter output = new XMLOutputter();
		output.output(doc, new FileOutputStream(Appconst.DATABASE_NAME));

		System.out.println("删除数据成功啦...................................");

		isDel = true;
		return isDel;
	}

	/**
	 * 查询所有数据
	 * 
	 * @param tableName
	 * @return
	 * @throws Exception
	 */
	public List<Map> queryAll(String tableName) throws Exception {
		FileInputStream fileIs = new FileInputStream(Appconst.DATABASE_NAME);
		SAXBuilder sAXBuilder = new SAXBuilder();
		Document doc = sAXBuilder.build(fileIs);
		Element rootElement = doc.getRootElement();
		Gson gson = new Gson();
		boolean flag = false;

		List<Map> dataListMap = new ArrayList<Map>();

		for (Element element : rootElement.getChildren()) {
			if (tableName.equals(element.getAttributeValue("name"))) {
				flag = true;
				List<Element> subElementList = element.getChildren();
				for (Element dataElement : subElementList) {
					Map dataMap = gson.fromJson(dataElement.getText(), Map.class);
					dataListMap.add(dataMap);
				}
			}
		}
		if (!flag) {
			throw new Exception("table '" + tableName + "' is not exits");
		}
		return dataListMap;

	}
}
